package com.hemerasolutions.v2trainer.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.stereotype.Repository;

import com.hemerasolutions.v2trainer.dao.interfaces.EquipmentDaoInterface;
import com.hemerasolutions.v2trainer.model.equipment.VersionableEquipment;
import com.hemerasolutions.v2trainer.model.equipment.VersionableEquipment_;
import com.hemerasolutions.v2trainer.model.exercise.Equipment;
import com.hemerasolutions.v2trainer.model.exercise.Equipment_;
import com.hemerasolutions.v2trainer.model.library.Library;
import com.hemerasolutions.v2trainer.model.users.Academy;
import com.hemerasolutions.v2trainer.model.users.Academy_;

@Repository(value = "equipmentDao")
public class EquipmentDao extends BaseDao<Equipment> implements EquipmentDaoInterface{
	private static final long serialVersionUID = 1L;

	@SuppressWarnings("unchecked")
	@Override
	public List<Equipment> searchEquipmentsOfAcademy(Map<String, Object> fields) {

		List<Predicate> predicateList = new ArrayList<Predicate>();

		CriteriaBuilder cb = this.getEntityManager().getCriteriaBuilder();

		CriteriaQuery<Equipment> cq  = cb.createQuery(Equipment.class);
		
		Root<Equipment> equipment = cq.from(Equipment.class);

		Root<Academy> academy = cq.from(Academy.class);

		academy.join(Academy_.equipments,JoinType.LEFT); 

		Predicate pred;


		
	    for (Map.Entry<String,Object> line : fields.entrySet()) {


	    	if( line.getKey().toString() == "academy"){
        		pred = cb.equal(academy.get(Academy_.id),(Academy)line.getValue());
                predicateList.add(pred);    		

	    	}else if(line.getKey().toString() == "name"){
	    		pred = cb.like(cb.upper(equipment.get(Equipment_.name)), "%"+line.getValue().toString().toUpperCase()+"%");
	    		predicateList.add(pred);    		

	    	}else if(line.getKey().toString() == "description"){
	    		pred = cb.like(cb.upper(equipment.get(Equipment_.description)), "%"+line.getValue().toString().toUpperCase()+"%");
	    		predicateList.add(pred);    		
	    	
	    	}else if(line.getKey().toString() == "obs"){
	    		pred = cb.like(cb.upper(equipment.get(Equipment_.obs)),	"%"+line.getValue().toString().toUpperCase()+"%");
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "begChangedAt" ){ 
	    		pred = cb.greaterThanOrEqualTo(equipment.get(Equipment_.lastChange), this.begDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "endChangedAt" ){ 
	    		pred = cb.lessThanOrEqualTo(equipment.get(Equipment_.lastChange), this.endDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "begCreatedAt" ){ 
	    		pred = cb.greaterThanOrEqualTo(equipment.get(Equipment_.createdAt), this.begDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "endCreatedAt" ){ 
	    		pred = cb.lessThanOrEqualTo(equipment.get(Equipment_.createdAt), this.endDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "librarys" ){
	    		Path<VersionableEquipment> ve =  equipment.get(Equipment_.versionableEquipment);
	    		
	    		Expression<Library> lib =  ve.get(VersionableEquipment_.library);
    	
	    		pred = lib.in((List<Library>)line.getValue());
	    		predicateList.add(pred);    		

	    	}else if( line.getKey().toString() == "active"){ 
	    		pred = cb.equal(equipment.get(Equipment_.active), (Boolean)line.getValue());
	    		predicateList.add(pred);    		
	       	}	    
	    	
	    	

	    }
	    
	    Predicate[] predicates = new Predicate[predicateList.size()];
	    predicateList.toArray(predicates);
	    cq.where(predicates);
	 
	    
	    return super.getEntityManager().createQuery(cq).getResultList();			
		

	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Equipment> searchEquipments(Map<String, Object> fields) {
		List<Predicate> predicateList = new ArrayList<Predicate>();

		CriteriaBuilder cb = this.getEntityManager().getCriteriaBuilder();

		CriteriaQuery<Equipment> cq  = cb.createQuery(Equipment.class);
		
		Root<Equipment> equipment = cq.from(Equipment.class);

		Predicate pred;
		
	    for (Map.Entry<String,Object> line : fields.entrySet()) {
	    	
	    	
	    	if(line.getKey().toString() == "name"){
	    		pred = cb.like(cb.upper(equipment.get(Equipment_.name)), "%"+line.getValue().toString().toUpperCase()+"%");
	    		predicateList.add(pred);    		

	    	}else if(line.getKey().toString() == "description"){
	    		pred = cb.like(cb.upper(equipment.get(Equipment_.description)), "%"+line.getValue().toString().toUpperCase()+"%");
	    		predicateList.add(pred);    		
	    	
	    	}else if(line.getKey().toString() == "obs"){
	    		pred = cb.like(cb.upper(equipment.get(Equipment_.obs)),	"%"+line.getValue().toString().toUpperCase()+"%");
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "begChangedAt" ){ 
	    		pred = cb.greaterThanOrEqualTo(equipment.get(Equipment_.lastChange), this.begDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "endChangedAt" ){ 
	    		pred = cb.lessThanOrEqualTo(equipment.get(Equipment_.lastChange), this.endDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "begCreatedAt" ){ 
	    		pred = cb.greaterThanOrEqualTo(equipment.get(Equipment_.createdAt), this.begDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "endCreatedAt" ){ 
	    		pred = cb.lessThanOrEqualTo(equipment.get(Equipment_.createdAt), this.endDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "librarys" ){
	    		Path<VersionableEquipment> ve =  equipment.get(Equipment_.versionableEquipment);
	    		
	    		Expression<Library> lib =  ve.get(VersionableEquipment_.library);
    	
	    		pred = lib.in((List<Library>)line.getValue());
	    		predicateList.add(pred);    		

	    	}else if( line.getKey().toString() == "active"){ 
	    		pred = cb.equal(equipment.get(Equipment_.active), (Boolean)line.getValue());
	    		predicateList.add(pred);    		
	       	}	    
	    }
	    
	    Predicate[] predicates = new Predicate[predicateList.size()];
	    predicateList.toArray(predicates);
	    cq.where(predicates);
	 
	    
	    return super.getEntityManager().createQuery(cq).getResultList();		
	}

}
